/*
 * @author 李立超
 * @date 2024-12-06 09:47:38
 * @description 罗马数字转换
 * @see 🚀 https://www.douyin.com/user/self?from_tab_name=main&modal_id=7280403813561912610&showTab=like
 * @status done
 */

/**
 * 罗马数字转换为整数
 * @param roman 罗马数字
 * @returns
 */
export function romanToInteger(roman: string): number {
  // 定义罗马数字与整数的映射关系
  const romanMap: Record<string, number> = {
    I: 1,
    V: 5,
    X: 10,
    L: 50,
    C: 100,
    D: 500,
    M: 1000
  } as const

  // 定义正则表达式，用于匹配罗马数字
  const reg = new RegExp(Object.keys(romanMap).join('|'), 'g')
  // 如果输入的罗马数字不合法，抛出错误
  if (!reg.test(roman)) {
    throw new Error('invalid roman')
  }

  // 初始化结果和左边的数字
  let result = 0,
    left = 0
  // 遍历罗马数字
  for (let i = 0; i < roman.length; i++) {
    // 获取当前罗马数字对应的整数
    const current = romanMap[roman[i]]
    // 如果当前数字大于左边的数字，则减去两倍的左边数字
    if (current > left) {
      result += current - left * 2
    } else {
      // 否则直接加上当前数字
      result += current
    }
    // 更新左边的数字
    left = current
  }
  // 返回结果
  return result
}

/**
 * 整数转换为罗马数字
 * @param num 整数
 * @returns
 */
export function integerToRoman(num: number): string {
  // 定义罗马数字的值和符号
  const val = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
  const syms = [
    'M',
    'CM',
    'D',
    'CD',
    'C',
    'XC',
    'L',
    'XL',
    'X',
    'IX',
    'V',
    'IV',
    'I'
  ]
  // 初始化罗马数字字符串
  let roman = ''
  // 遍历罗马数字的值
  for (let i = 0; i < val.length; i++) {
    // 如果当前值小于等于num，则将当前值减去num，并将当前符号添加到罗马数字字符串中
    while (num >= val[i]) {
      num -= val[i]
      roman += syms[i]
    }
  }
  // 返回罗马数字字符串
  return roman
}
